﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BLToolkit.Data;

namespace Platform.Model
{
	/// <summary>
	/// Lop quan ly danh sach cac kho cua sieu thi
	/// </summary>
	public class Warehouse
	{
		private List<Store> _storages;
		private Dictionary<string, Store> _mapper;

		/// <summary>
		/// Khoi tao doi tuong quan ly danh sach cac kho cua sieu thi
		/// </summary>
		public Warehouse()
		{
		}

		/// <summary>
		/// Tai danh sach cac kho cua sieu thi vao bo nho
		/// </summary>
		/// <param name="lastRefresh">Thoi diem tai du lieu gan nhat</param>
		public void Refresh(DateTime? lastRefresh = null)
		{
			if (lastRefresh == null)
			{
				// Lay danh sach cac kho cua sieu thi
				_storages = Store.Objects.Where(x => x.MarketId == WorkSession.Current.Market.ID).ToList();
				// Tao tu dien de anh xa giua Store No va ID
				_mapper = _storages.ToDictionary(x => x.StoreNo, x => x);
			}
			else
			{
				var houses = Store.Objects.Where(x => x.MarketId == WorkSession.Current.Market.ID
				                                         && x.LastUpdated > lastRefresh.Value).ToList();
				foreach (var store in houses)
				{
					if (_mapper.ContainsKey(store.StoreNo))
						_mapper[store.StoreNo] = store;
					else
						_mapper.Add(store.StoreNo, store);
				}
				_storages = _mapper.Values.ToList();
			} // end if
		} // end method

		/// <summary>
		/// Lay cac kho cua sieu thi theo ma so Store No
		/// </summary>
		/// <param name="storeNo">Ma so cua kho</param>
		/// <returns>Tra ve kho cua sieu thi co ma la storeNo hoac null</returns>
		public Store GetStore(string storeNo)
		{
			return _mapper.ContainsKey(storeNo) ? _mapper[storeNo] : null;
		}

		/// <summary>
		/// Lay ID cua kho trong sieu thi theo ma so Store No
		/// </summary>
		/// <param name="storeNo">Ma so cua kho</param>
		/// <returns>Tra ve ID cua mat hang hoac bao loi neu khong tim thay</returns>
		public int GetStoreId(string storeNo)
		{
			var warehouse = GetStore(storeNo);
			if (warehouse == null)
				throw new NullReferenceException("Khong tim thay mat hang co ma " + storeNo);

			return warehouse.Id;
		}

        /// <summary>
        /// Them hoac sua Kho (Store)
        /// </summary>
        /// <param name="st">Kho</param>
        /// <returns>Tra ve gia tri Store.Id</returns>
        public int AddOrUpdate(Store st)
        {
            // Kho moi nhung co ma trung voi kho cu
            // khong them duoc => thong bao loi
            if (st.Id == 0 && _mapper.ContainsKey(st.StoreNo))
                throw new DuplicateNameException("Cannot add new article with duplicate ART_NO");

            // Them moi kho
            if (st.Id == 0)
            {
                st.Insert();
                _mapper.Add(st.StoreNo, st);
            }
            // truong hop cap nhat
            else
            {
                // Tim kho da co trong danh sach theo id
                var store = _storages.FirstOrDefault(x => x.Id == st.Id);

                // TRuong hop nhap ma moi nhung trung voi kho khac
                if (st.StoreNo != store.StoreNo && _mapper.ContainsKey(st.StoreNo))
                    throw new DuplicateNameException("Cannot update article with duplicate ART_NO");

                st.Update();

                // Cap nhat gia tri moi cho kho hang
                store.StoreNo = st.StoreNo;
                store.StoreName = st.StoreName;
                store.Address = st.Address;
                store.LastUpdated = st.LastUpdated;

                // Xoa thong tin kho cu
                _mapper.Remove(store.StoreNo);

                // thay doi bang kho moi vua cap nhat
                _mapper.Add(st.StoreNo, st);
            }

            return st.Id;
        }

		/// <summary>
		/// Lay danh sach cac kho trong sieu thi
		/// </summary>
		/// <returns>Danh sach tat ca cac kho trong sieu thi</returns>
		public List<Store> ToList()
		{
			return _storages;
		}
	}
}
